/**
 * 
 */
package com.android.avy;

import java.util.Map.Entry;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;

/**
 * @author heycosmo
 *
 */
public class AvyProvider extends ContentProvider {
	
	public static final String TAG = "AvyProvider";
	
	public static final String DATABASE_NAME = "zonedata.db";

	public static final int DATABASE_VERSION = 2;
		
	static public final String[] ROSE_PROJ = new String[] {
		ZoneData.ZoneDays._ID,
		ZoneData.ZoneDays.COL_NAME_ROSE
	};
	
	private static final UriMatcher sUriMatcher;
	
	static public final int ZONE_DAY_ID = 1;
	static public final int ALL_ZONE_DAYS = 2;

	
	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);		
		sUriMatcher.addURI(ZoneData.AUTHORITY, "zonedays", ALL_ZONE_DAYS);
		sUriMatcher.addURI(ZoneData.AUTHORITY, "zonedays/#", ZONE_DAY_ID);		
	}
	
	private DatabaseHelper mOpenHelper;

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#delete(android.net.Uri, java.lang.String, java.lang.String[])
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		
		switch (sUriMatcher.match(uri)) {
		// In this case, the client is requesting to delete a specific row
		case ZONE_DAY_ID:
			// get id
			String zonedayId = uri.getPathSegments().get(ZoneData.ZoneDays.ZONEDAY_ID_PATH_POSITION);
			String where = ZoneData.ZoneDays._ID + "=" + zonedayId;
			
			if (selection != null) {
				where = where + " AND " + selection;
			}
			
			count = db.delete(ZoneData.ZoneDays.TABLE_NAME, where, selectionArgs);
			break;
		case ALL_ZONE_DAYS:
			count = db.delete(ZoneData.ZoneDays.TABLE_NAME, selection, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		/*Gets a handle to the content resolver object for the current context, and notifies it
         * that the incoming URI changed. The object passes this along to the resolver framework,
         * and observers that have registered themselves for the provider are notified.
         */
        getContext().getContentResolver().notifyChange(uri, null);

        // Returns the number of rows deleted.
        return count;
	}

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#getType(android.net.Uri)
	 */
	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case ZONE_DAY_ID:
			return ZoneData.ZoneDays.CONTENT_TYPE_ITEM;
		case ALL_ZONE_DAYS:
			return ZoneData.ZoneDays.CONTENT_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#insert(android.net.Uri, android.content.ContentValues)
	 */
	@Override
	public Uri insert(Uri uri, ContentValues initValues) {
		
		if (sUriMatcher.match(uri) != ALL_ZONE_DAYS) {
			throw new IllegalArgumentException(uri + " does not refer to zonedays table");
		}
		
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		
		ContentValues values = new ContentValues(initValues);
		
		if (values.containsKey(ZoneData.ZoneDays.COL_NAME_DATE) == false) {
			values.put(ZoneData.ZoneDays.COL_NAME_DATE, 0);
		}
		
		///* debug
		for (Entry<String, Object> e : values.valueSet()) {
			Log.d("AVY", (String) e.getValue());
			Log.d("AVY", e.getKey());
		}
		//*/
		
		// Performs the insert and returns the ID of the new note.
        long rowId = db.insert(
            ZoneData.ZoneDays.TABLE_NAME,        // The table to insert into.
            ZoneData.ZoneDays.COL_NAME_ROSE,  // A hack, SQLite sets this column value to null
                                             // if values is empty.
            values                           // A map of column names, and the values to insert
                                             // into the columns.
        );
        
        // If the insert succeeded, the row ID exists.
        if (rowId > 0) {
            // Creates a URI with the note ID pattern and the new row ID appended to it.
            Uri noteUri = ContentUris.withAppendedId(ZoneData.ZoneDays.CONTENT_URI_BASE, rowId);

            // Notifies observers registered against this provider that the data changed.
            getContext().getContentResolver().notifyChange(noteUri, null);
            return noteUri;
        }

        // If the insert didn't succeed, then the rowID is <= 0. Throws an exception.
        throw new SQLException("Failed to insert row into " + uri);
        
	}

	/**
	 * @see android.content.ContentProvider#onCreate()
	 * Just creates a new DatabaseHelper
	 */
	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
			String sortOrder) {

		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(ZoneData.ZoneDays.TABLE_NAME);
		
		switch (sUriMatcher.match(uri)) {
		case ZONE_DAY_ID:
			qb.appendWhere(ZoneData.ZoneDays._ID + 
					"=" + 
					uri.getPathSegments().get(ZoneData.ZoneDays.ZONEDAY_ID_PATH_POSITION));
			break;
		case ALL_ZONE_DAYS:
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
		int count = c.getCount();
		c.setNotificationUri(getContext().getContentResolver(), uri);
		
		return c;
	}

	/**
     * This is called when a client calls
     * {@link android.content.ContentResolver#update(Uri,ContentValues,String,String[])}
     * Updates records in the database. The column names specified by the keys in the values map
     * are updated with new data specified by the values in the map. If the incoming URI matches the
     * note ID URI pattern, then the method updates the one record specified by the ID in the URI;
     * otherwise, it updates a set of records. The record or records must match the input
     * selection criteria specified by where and whereArgs.
     * If rows were updated, then listeners are notified of the change.
     *
     * @param uri The URI pattern to match and update.
     * @param values A map of column names (keys) and new values (values).
     * @param where An SQL "WHERE" clause that selects records based on their column values. If this
     * is null, then all records that match the URI pattern are selected.
     * @param whereArgs An array of selection criteria. If the "where" param contains value
     * placeholders ("?"), then each placeholder is replaced by the corresponding element in the
     * array.
     * @return The number of rows updated.
     * @throws IllegalArgumentException if the incoming URI pattern is invalid.
     */
	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		
		switch (sUriMatcher.match(uri)) {
		case ZONE_DAY_ID:
			// get id
			String zonedayId = uri.getPathSegments().get(ZoneData.ZoneDays.ZONEDAY_ID_PATH_POSITION);
			String where = ZoneData.ZoneDays._ID + "=" + zonedayId;
			
			if (selection != null) {
				where = where + " AND " + selection;
			}
			count = db.update(ZoneData.ZoneDays.TABLE_NAME, values, where, selectionArgs);
			break;
		case ALL_ZONE_DAYS:
			count = db.update(ZoneData.ZoneDays.TABLE_NAME, values, selection, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		/*Gets a handle to the content resolver object for the current context, and notifies it
         * that the incoming URI changed. The object passes this along to the resolver framework,
         * and observers that have registered themselves for the provider are notified.
         */
        getContext().getContentResolver().notifyChange(uri, null);

        // Returns the number of rows updated.
        return count;
	}

	 /**
    *
    * This class helps open, create, and upgrade the database file. Set to package visibility
    * for testing purposes.
    */
   private class DatabaseHelper extends SQLiteOpenHelper {

       DatabaseHelper(Context context) {
           // calls the super constructor, requesting the default cursor factory.
           super(context, DATABASE_NAME, null, DATABASE_VERSION);
       }

       /**
        *
        * Creates the underlying database with table name and column names taken from the
        * NotePad class.
        */
       @Override
       public void onCreate(SQLiteDatabase db) {
           db.execSQL("CREATE TABLE " + ZoneData.ZoneDays.TABLE_NAME + " ("
                   + ZoneData.ZoneDays._ID + " INTEGER PRIMARY KEY,"
                   + ZoneData.ZoneDays.COL_NAME_ZONE + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_STATE + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_DATE + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_ROSE + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_TEMPS + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_SNOWFALL + " TEXT,"
                   + ZoneData.ZoneDays.COL_NAME_MODIFICATION_DATE + " INTEGER"
                   + ZoneData.ZoneDays.COL_NAME_STATEMENT + " TEXT,"
                   + ");");
       }

       /**
        *
        * Demonstrates that the provider must consider what happens when the
        * underlying datastore is changed. In this sample, the database is upgraded the database
        * by destroying the existing data.
        * A real application should upgrade the database in place.
        */
       @Override
       public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

           // Logs that the database is being upgraded
           Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                   + newVersion + ", which will destroy all old data");

           // Kills the table and existing data
           db.execSQL("DROP TABLE IF EXISTS " + ZoneData.ZoneDays.TABLE_NAME);

           // Recreates the database with a new version
           onCreate(db);
       }
       
       
   }
   

}
